package com.hotel.BL;

import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

import com.EntityName;
import com.google.appengine.api.datastore.Entity;
import com.google.appengine.api.datastore.EntityNotFoundException;
import com.google.appengine.api.datastore.FetchOptions;
import com.google.appengine.api.datastore.Key;
import com.google.appengine.api.datastore.KeyFactory;
import com.google.appengine.api.datastore.Query;
import com.google.appengine.api.datastore.Query.CompositeFilterOperator;
import com.google.appengine.api.datastore.Query.Filter;
import com.google.appengine.api.datastore.Query.FilterOperator;
import com.google.appengine.api.datastore.Query.FilterPredicate;

import data.Department;
import data.General;
import data.Hotel;
import data.POS;
import data.Salutation;
import data.User;
import data.UserLevel;
import data.UserMappingHotel;
import data.passingData.UserData4Admin;
import data.passingData.UserData4AdminEdit;
import data.passingData.UserLogedinData;

public class UserLogic extends AbstractBL {
	public UserLogic(HttpServletRequest req,HttpServletResponse resp){
		this.req = req;
		this.resp = resp;
	}
	public List<User> GenerateUser(long hotelId) {
		List<User> list = new ArrayList<User>();
		
		Salutation salutation = new SalutationLogic().GetSalutation(hotelId, "Mr.");
		Salutation salutation2 = new SalutationLogic().GetSalutation(hotelId, "Ms.");
		String language = new GenericLogic(req, resp).GetGeneral(hotelId).getDefaultLanguageString();
		User user;
		if(GetUser("jesus.way@hotmail.com","opensource") == null){
			user = new User();
			user.setSalutation(salutation);
			user.setFirstName("Montree");
			user.setAddress("address");
			user.setCountryCodeISO3("THA");
			user.setState("");
			user.setCity("");
			user.setZipCode("");
			user.setPhone("");
			user.setMobile("");
			user.setEmergencyNumber("");
			user.setGender("M");
			//user.setBirthday(Date);
			user.setIdentificationNo("");
			user.setPassportNumber("");
			user.setDriverlicense("");
			user.setSocialSecuritycard("");
			user.setBloodGroup("O");
			user.setDesignation("");
			user.setEmail("jesus.way@hotmail.com");
			user.setPassword("opensource");
			user.setCommentText("");
			user.setLanguageString(language);
			list.add(user);
		}
		if(GetUser("-","-") == null){
			user = new User();
			user.setSalutation(salutation2);
			user.setFirstName("Sarawee");
			user.setAddress("address");
			user.setCountryCodeISO3("THA");
			user.setState("");
			user.setCity("");
			user.setZipCode("");
			user.setPhone("");
			user.setMobile("");
			user.setEmergencyNumber("");
			user.setGender("F");
			//user.setBirthday(Date);
			user.setIdentificationNo("");
			user.setPassportNumber("");
			user.setDriverlicense("");
			user.setSocialSecuritycard("");
			user.setBloodGroup("O");
			user.setDesignation("");
			user.setEmail("-");
			user.setPassword("-");
			user.setCommentText("");
			user.setLanguageString(language);
			list.add(user);
		}
		if(GetUser("-","02") == null){
			user = new User();
			user.setSalutation(salutation2);
			user.setFirstName("Pawadee");
			user.setAddress("address");
			user.setCountryCodeISO3("THA");
			user.setState("");
			user.setCity("");
			user.setZipCode("");
			user.setPhone("");
			user.setMobile("");
			user.setEmergencyNumber("");
			user.setGender("F");
			//user.setBirthday(Date);
			user.setIdentificationNo("");
			user.setPassportNumber("");
			user.setDriverlicense("");
			user.setSocialSecuritycard("");
			user.setBloodGroup("O");
			user.setDesignation("");
			user.setEmail("-");
			user.setPassword("02");
			user.setCommentText("");
			user.setLanguageString(language);
			list.add(user);
		}
		return list;
	}
	
	public void AddUserMapping(long hotelId,String userId,String department){
		Department front = new DepartmentLogic().GetDepartment(hotelId,department);
		UserLevel userlv = new UserLevelLogic(req,resp).GetUserLevel(hotelId, "Admin");
		if(new UserMappingHotelLogic(req, resp).GetUserMapping(hotelId,userId) == null)
		{
			UserMappingHotel usrMapping = new UserMappingHotel();
			usrMapping.setHotelId(hotelId);
			//usrMapping.setDisplayId(GetMaxUserDisplayId(hotelId)+1);
			usrMapping.setUserString(String.valueOf(userId));
			usrMapping.setDepartmentString(String.valueOf(front.getId()));
			usrMapping.setUserlevelString(String.valueOf(userlv.getId()));
			usrMapping.setStatus(true);
			usrMapping.setAvaliable(true);
			datastore.put(usrMapping.getEntity());
		}
	}
	
	public User GetUser(long id) {
		Key key = KeyFactory.createKey(EntityName.User, id);
		try {
			Entity lang = datastore.get(key);
			User c = new User();
			c.setEntity(lang);
			return c;
		} catch (EntityNotFoundException e) {
			return null;
		}
	}

	public User GetUser(String email, String pass) {
		Query q = new Query(EntityName.User);

		Filter filterEmail = new FilterPredicate("email", FilterOperator.EQUAL,
				email);
		Filter filterPass = new FilterPredicate("password",
				FilterOperator.EQUAL, pass);

		Filter filter = CompositeFilterOperator.and(filterEmail, filterPass);
		
		q.setFilter(filter);
		Entity s = datastore.prepare(q).asSingleEntity() ;
		if(s != null){
			return GetUser(s);
		}else{
			return null;
		}
	}

	public List<User> GetAllUser(long employeeId) {
		Query q = new Query(EntityName.User);

		Filter filterHotel = new FilterPredicate("employeeId",
				FilterOperator.EQUAL, employeeId);

		Filter filter = CompositeFilterOperator.and(filterHotel);

		q.setFilter(filter);

		return GetList(datastore.prepare(q).asList(
				FetchOptions.Builder.withDefaults()));
	}
	
	public List<User> GetUserFromDepartment(long hotelId,long departmentId) {
		List<UserMappingHotel> list = new UserMappingHotelLogic(req, resp).GetAllUserFromHotel(hotelId);
		List<User> userlist = new ArrayList<User>();
		for(int i=0;i<list.size();i++)
		{
			if(list.get(i).getHotelId() == hotelId){
				long userId = Long.parseLong(list.get(i).getUserString());
				User user = GetUser(userId);
				if(user!=null &&  list.get(i).getDepartment().getId() == departmentId)
					userlist.add(user);
			}
			
		}
		return userlist;
	}

	public User GetUser(Entity entity) {
		User item = new User();
		item.setEntity(entity);
		return item;
	}
	public List<User> GetList(List<Entity> entities) {
		List<User> list = new ArrayList<User>();
		if(entities!=null)
		for (Entity e : entities) {
			User a = new User();
			a.setEntity(e);
			list.add(a);
		}
		return list;
	}
	
//	public long GetMaxUserDisplayId(long hotelId)
//	{
//		Query q = new Query(EntityName.UserMappingHotel);
//
//		Filter filterHotel = new FilterPredicate("hotelId",
//				FilterOperator.EQUAL, hotelId);
//		q.setFilter(filterHotel).addSort("displayId", SortDirection.DESCENDING);
//
//		List<UserMappingHotel> list = GetUserMappingList(datastore.prepare(q).asList(
//				FetchOptions.Builder.withLimit(1)));
//		if(list.size()>0)
//			return list.get(0).getDisplayId();
//		return 0;
//	}
	
	public User UpdateUser(User user)
	{
		Key key = datastore.put(user.getEntity());
		user.setId(key.getId());
		user.setKey(key);
		return user;
	}
	
	public List<UserLogedinData> GetLogedInUser(long hotelId) {
		Date date = new GenericLogic(req,resp).ServerDateTime(hotelId);
		List<UserLogedinData> userlogedin = new ArrayList<UserLogedinData>();
		List<UserMappingHotel> mapping = new UserMappingHotelLogic(req, resp).GetAllUserFromHotel(hotelId);
		for(int i=0;i<mapping.size();i++){
			User user = GetUser(Long.parseLong(mapping.get(i).getUserString()));
			if(date.getTime() - user.getLastStay().getTime() < 300000){
				UserLogedinData userlogin = new UserLogedinData();
				userlogin.setId(user.getId());
				userlogin.setCountername(mapping.get(i).getUserlevel().getDefaultWorkAreas().getTitle());
				userlogin.setEmail(user.getEmail());
				userlogin.setLastname(user.getLastName());
				userlogin.setName(user.getFirstName());

				userlogedin.add(userlogin);
			}
		}
		return userlogedin;
	}
	
	public User GetLastUserInCounter(long hotelId,long counterId,Date dateFrom,Date dateTo) {
		Query q = new Query(EntityName.User);

		Filter filterHotelId = new FilterPredicate("hotelId", FilterOperator.EQUAL,
				hotelId);
		Filter filterCounter = new FilterPredicate("lastCounter",
				FilterOperator.EQUAL, String.valueOf(counterId));
		Filter filterDateFrom = new FilterPredicate("lastStay",
				FilterOperator.GREATER_THAN_OR_EQUAL, dateFrom);
		Filter filterTo = new FilterPredicate("lastStay",
				FilterOperator.LESS_THAN_OR_EQUAL, dateTo);
		Filter filter = CompositeFilterOperator.and(filterHotelId,
				filterCounter,filterDateFrom,filterTo);
		
		q.setFilter(filter);
		List<User> userList =  GetList(datastore.prepare(q).asList(FetchOptions.Builder.withDefaults()));
		if(userList.size() == 0){
			return null;
		}else{
			User lastUser = userList.get(0);
			for(int i=0;i<userList.size();i++){
				if(lastUser.getLastStay().getTime() < userList.get(i).getLastStay().getTime()){
					lastUser = userList.get(i);
				}
			}
			return lastUser;
		}
	}

	public List<UserData4Admin> GetAllUser4AdminLimit(long hotelId,long offset,long line)
	{
		Query q = new Query(EntityName.UserMappingHotel);
		
		Filter filterHotel = new FilterPredicate("hotelId",FilterOperator.EQUAL,hotelId);
		Filter filterAvaliable = new FilterPredicate("avaliable",FilterOperator.EQUAL,true);

		Filter filter = CompositeFilterOperator.and(filterHotel, filterAvaliable);
		
		q.setFilter(filter);
		
		return ToUserData4Admin(new UserMappingHotelLogic(req, resp).GetUserMappingList(datastore.prepare(q).asList(FetchOptions.Builder.withLimit((int) line).offset((int)offset))));
	}
	
	public List<UserData4Admin> ToUserData4Admin(List<UserMappingHotel> list){
		List<UserData4Admin> data = new ArrayList<UserData4Admin>();
		for(int i=0;i<list.size();i++){
			UserData4Admin d = new UserData4Admin();
			User user = list.get(i).getUser();
			d.setUserId(user.getId());
			d.setMappingId(list.get(i).getId());
			String name = user.getFirstName();
			if(user.getLastName()!=null){
				name += " " + user.getLastName();
			}
			d.setName(name);
			d.setEmail(list.get(i).getUser().getEmail());
			d.setUserLevel(list.get(i).getUserlevel().getTitle());
			d.setStatus(list.get(i).isStatus());
			List<String> sList = new ArrayList<String>();
			List<POS> pos = list.get(i).getUserlevel().getWorkAreas();
			for(int x=0;x<pos.size();x++){
				sList.add(pos.get(x).getTitle());
			}
			d.setPos(sList);
			data.add(d);
		}
		return data;
	}
	
	public User Add(long hotelId,String address,Date birthday,
			String bloodGroup,String  city,String country,Date dateOfJoin,String designation,
			String driverLicense,String emergencyNumber,String firstName,String gender,
			String identificationNo,String lastName,String mobile,String passportNumber,
			String phone,String socialSecurityCard,String state,String zipCode,String email,String pass)
			throws EntityNotFoundException{
		User a = new User();
		
		a.setAddress(address);
		a.setBirthday(birthday);
		a.setBloodGroup(bloodGroup);
		a.setCity(city);
		a.setCountryCodeISO3(country);
		a.setDateOfJoin(dateOfJoin);
		a.setDesignation(designation);
		a.setDriverlicense(driverLicense);
		a.setEmergencyNumber(emergencyNumber);
		a.setFirstName(firstName);
		a.setGender(gender);
		a.setIdentificationNo(identificationNo);
		a.setLastName(lastName);
		a.setMobile(mobile);
		a.setPassportNumber(passportNumber);
		a.setPhone(phone);
		a.setSocialSecuritycard(socialSecurityCard);
		a.setState(state);
		a.setZipCode(zipCode);
		a.setEmail(email);
		a.setPassword(pass);
		a.setLanguageString(new GenericLogic(req, resp).GetGeneral(hotelId).getDefaultLanguageString());

		Key k = datastore.put(a.getEntity());
		a.setId(k.getId());
		a.setKey(k);
		
		return a;
	}

	public User Edit(long id,String address,Date birthday,
			String bloodGroup,String  city,String country,Date dateOfJoin,String designation,
			String driverLicense,String emergencyNumber,String firstName,String gender,
			String identificationNo,String lastName,String mobile,String passportNumber,
			String phone,String socialSecurityCard,String state,String zipCode,String email,String pass)
			throws EntityNotFoundException{
		User a = GetUser(id);
		
		a.setAddress(address);
		a.setBirthday(birthday);
		a.setBloodGroup(bloodGroup);
		a.setCity(city);
		a.setCountryCodeISO3(country);
		a.setDateOfJoin(dateOfJoin);
		a.setDesignation(designation);
		a.setDriverlicense(driverLicense);
		a.setEmergencyNumber(emergencyNumber);
		a.setFirstName(firstName);
		a.setGender(gender);
		a.setIdentificationNo(identificationNo);
		a.setLastName(lastName);
		a.setMobile(mobile);
		a.setPassportNumber(passportNumber);
		a.setPhone(phone);
		a.setSocialSecuritycard(socialSecurityCard);
		a.setState(state);
		a.setZipCode(zipCode);
		a.setEmail(email);
		a.setPassword(pass);

		Key k = datastore.put(a.getEntity());
		a.setId(k.getId());
		a.setKey(k);
		
		return a;
	}
	
	public UserData4AdminEdit ToUserData4AdminEdit(User u){
		HttpSession session=req.getSession(true);	
		long hotelId = (Long) session.getAttribute("hotelId");
		UserMappingHotel m = new UserMappingHotelLogic(req, resp).
				GetUserMapping(hotelId, String.valueOf(u.getId()));
		UserData4AdminEdit a = new UserData4AdminEdit();
		a.setAddress(u.getAddress());
		a.setBirthday(u.getBirthday());
		a.setBloodGroup(u.getBloodGroup());
		a.setCity(u.getCity());
		a.setCountryCodeISO3(u.getCountryCodeISO3());
		a.setDateOfJoin(u.getDateOfJoin());
		a.setDesignation(u.getDesignation());
		a.setDriverlicense(u.getDriverlicense());
		a.setEmergencyNumber(u.getEmergencyNumber());
		a.setFirstName(u.getFirstName());
		a.setGender(u.getGender());
		a.setIdentificationNo(u.getIdentificationNo());
		a.setLastName(u.getLastName());
		a.setMobile(u.getMobile());
		a.setPassportNumber(u.getPassportNumber());
		a.setPhone(u.getPhone());
		a.setSocialSecuritycard(u.getSocialSecuritycard());
		a.setState(u.getState());
		a.setZipCode(u.getZipCode());
		a.setEmail(u.getEmail());
		a.setPassword(u.getPassword());
		a.setDepartment(m.getDepartmentString());
		a.setUserlevel(m.getUserlevelString());
		return a;
	}
	
	public HashMap<String, Object> UserDataForChoseWorkAreaPage(){
		HttpSession session=req.getSession(true);
		
		Long hotelId = (Long)session.getAttribute("hotelId");
		long userid = (Long)session.getAttribute("userid");
		
		User user = GetUser(userid);
		UserMappingHotel mapping = new UserMappingHotelLogic(req, resp).GetUserMapping(hotelId, String.valueOf(userid));
		General general = new GenericLogic(req, resp).GetGeneral(hotelId);
		Hotel hotel = new HotelLogic().GetHotelByHotelId(hotelId);
		HashMap<String, Object> userData = new HashMap<String, Object>();
		String fullname = user.getFirstName();
		if(user.getLastName() != null)
			fullname += " " + user.getLastName();
		userData.put("name", fullname);
		userData.put("userLevel", mapping.getUserlevel().getTitle());
		userData.put("email", user.getEmail());
		userData.put("hotelName", hotel.getHotelName());
		//userData.put("displayPic", value);
		userData.put("lastNightAudit",general.getLastNightAudit());
		
		return userData;
	}
}
